package weiyao.xinxidasai.controller;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import weiyao.xinxidasai.DTO.Result;
import weiyao.xinxidasai.service.ChunkService;
import weiyao.xinxidasai.service.UploadService;

import javax.annotation.PostConstruct;
import java.io.*;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@RestController
@RequestMapping("/file")
@CrossOrigin
public class UploadController {
    private static final Logger logger = LoggerFactory.getLogger(UploadController.class);

    @Value("${file.path}")
    private String filePath;

    @Autowired
    private UploadService uploadService;

    @Autowired
    private ChunkService chunkService;

    // 确保临时目录存在
    @PostConstruct
    public void init() {
        File dir = new File(filePath);
        if (!dir.exists()) {
            dir.mkdirs();
            logger.info("创建临时目录: {}", filePath);
        }
    }

    @PostMapping("/upload")
    public Result uploadFile(
            @RequestParam("file") MultipartFile file,
            @RequestParam("folderId") Long folderId,
            @RequestParam("versionId") Long versionId,
            @RequestParam("encryptionType")String encryptionType ) {
        try {
            uploadService.processAndSaveFile(file, folderId, versionId,encryptionType);
            return Result.ok("文件上传成功");
        } catch (Exception e) {
            logger.error("文件上传失败", e);
            return Result.fail("文件上传失败: " + e.getMessage());
        }
    }

    // 文件检查接口
    @GetMapping("/check")
    public Result checkFile(@RequestParam("md5") String md5) {
        logger.info("检查MD5: {}", md5);
        Boolean isUploaded = uploadService.selectFileByMd5(md5) != null;
        Map<String, Object> data = new HashMap<>();
        data.put("isUploaded", isUploaded);

        if (isUploaded) {
            return Result.ok("文件已存在，可秒传", data);
        }

        List<Integer> chunkList = chunkService.selectChunkListByMd5(md5);
        data.put("chunkList", chunkList);
        return Result.ok("需继续上传分片", data);
    }

    // 重构：分片上传接口
    @PostMapping("/upload/chunk")
    public Result uploadChunk(
            @RequestParam("chunk") MultipartFile chunk,
            @RequestParam("md5") String md5,
            @RequestParam("index") Integer index,
            @RequestParam("chunkTotal") Integer chunkTotal,
            @RequestParam("fileSize") Long fileSize,
            @RequestParam("fileName") String fileName,
            @RequestParam("chunkSize") Long chunkSize,
            @RequestParam("folderId") Long folderId,
            @RequestParam("versionId") Long versionId,
            @RequestParam("encryptionType")String encryptionType
    ) {

        try {
            // 1. 保存分片到临时目录
            String chunkFilePath = saveChunkToTempFile(chunk, md5, index);

            // 2. 如果是最后一个分片，则合并并处理文件
            if (Objects.equals(index, chunkTotal)) {
                // 合并分片
                String mergedFilePath = mergeChunks(md5, chunkTotal, fileSize, fileName);

                // 处理文件（加密并上传到OSS）
                uploadService.processAndSaveFileFromDisk(mergedFilePath, fileName, folderId, versionId, md5,encryptionType);

                // 清理分片记录
                chunkService.deleteChunkByMd5(md5);

                return Result.ok("文件上传成功");
            }

            return Result.ok("分片上传成功", index);
        } catch (Exception e) {
            logger.error("分片上传失败", e);
            return Result.fail("分片上传失败: " + e.getMessage());
        }
    }

    // 保存分片到临时文件
    private String saveChunkToTempFile(MultipartFile chunk, String md5, Integer index) throws IOException {
        String chunkFileName = md5 + "_" + index + ".part";
        String chunkFilePath = filePath + chunkFileName;

        try (InputStream inputStream = chunk.getInputStream();
             FileOutputStream outputStream = new FileOutputStream(chunkFilePath)) {

            byte[] buffer = new byte[8192];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
        }

        logger.info("保存分片: {} (大小: {} 字节)", chunkFilePath, chunk.getSize());
        return chunkFilePath;
    }

    // 合并分片
    private String mergeChunks(String md5, int chunkTotal, long fileSize, String fileName) throws IOException {
        String mergedFilePath = filePath + md5 + "_" + fileName;
        File mergedFile = new File(mergedFilePath);

        try (FileOutputStream fos = new FileOutputStream(mergedFile, true)) {
            for (int i = 1; i <= chunkTotal; i++) {
                String chunkPath = filePath + md5 + "_" + i + ".part";
                File chunkFile = new File(chunkPath);

                if (!chunkFile.exists()) {
                    throw new FileNotFoundException("分片文件不存在: " + chunkPath);
                }

                // 读取分片内容并追加到合并文件
                try (FileInputStream fis = new FileInputStream(chunkFile)) {
                    byte[] buffer = new byte[8192];
                    int bytesRead;
                    while ((bytesRead = fis.read(buffer)) != -1) {
                        fos.write(buffer, 0, bytesRead);
                    }
                }

                // 删除分片文件
                Files.deleteIfExists(chunkFile.toPath());
            }
        }

        // 验证文件大小
        if (mergedFile.length() != fileSize) {
            throw new IOException("文件大小不匹配! 预期: " + fileSize + ", 实际: " + mergedFile.length());
        }

        logger.info("合并文件成功: {} (大小: {} 字节)", mergedFilePath, mergedFile.length());
        return mergedFilePath;
    }

    // 辅助方法：获取文件扩展名
    private String getFileExtension(String fileName) {
        int dotIndex = fileName.lastIndexOf(".");
        return (dotIndex > 0) ? fileName.substring(dotIndex + 1) : "";
    }
}